package com.loyal.kit;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;

import androidx.activity.result.ActivityResultLauncher;
import androidx.core.content.FileProvider;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.lang.reflect.Method;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

public class DeviceHelper {

    public static final int REQUEST_CODE_APP_INSTALL = 100;

    /**
     * 是否拥有悬浮窗权限
     * &lt;uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/&gt;
     * &lt;uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/&gt;
     */
    public static boolean hasOverlaysPermission(Context context) {
        if (null == context)
            return false;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            return Settings.canDrawOverlays(context);
        } else return true;
    }

    /**
     * 授予悬浮窗权限
     * &lt;uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/&gt;
     * &lt;uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/&gt;
     */
    public static void grantOverlaysPermission(Activity activity, ActivityResultLauncher<Intent> launcher) {
        if (null == activity) {
            return;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:" + activity.getPackageName()));
            if (null == launcher) {
                activity.startActivity(intent);
                activity.finish();
            } else {
                //在某些设备上使用下面代码会出现授权后，在onActivityResult方法中，依然提示未授权
                //context.startActivityForResult(intent, REQUEST_CODE_APP_OVERLAYS);
                launcher.launch(intent);
            }
        }
    }

    /**
     * 获取进程名称
     * 判断是否主进程
     */
    public static String getProcessName() {
        try {
            File file = new File("/proc/" + android.os.Process.myPid() + "/" + "cmdline");
            BufferedReader mBufferedReader = new BufferedReader(new FileReader(file));
            String processName = mBufferedReader.readLine().trim();
            mBufferedReader.close();
            return processName;
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 在8.0系统上是否有安装权限
     * &lt;uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/&gt;
     *
     * @param manager context.getPackageManager()
     */
    public static boolean canInstallPackage(PackageManager manager) {
        if (null == manager)
            return false;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            return manager.canRequestPackageInstalls();
        } else return true;
    }

    /**
     * 授予安装权限
     * &lt;uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/&gt;
     */
    public static void grantInstallPermission(Activity context) {
        if (context == null) {
            return;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            Uri packageURI = Uri.parse("package:" + context.getPackageName());
            Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI);
            context.startActivityForResult(intent, REQUEST_CODE_APP_INSTALL);
        }
    }

    /**
     * 授予安装权限
     * &lt;uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/&gt;
     */
    public static void grantInstallPermission(Context context, ActivityResultLauncher<Intent> launcher) {
        if (null == context || null == launcher) {
            return;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            Uri packageURI = Uri.parse("package:" + context.getPackageName());
            Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI);
            //context.startActivityForResult(intent, REQUEST_CODE_APP_INSTALL);
            launcher.launch(intent);
        }
    }

    /**
     * 安装程序
     * 需要如下权限
     * &lt;uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/&gt;
     *
     * @param uriFile 安装文件存放路径
     */
    public static void install(Context context, File uriFile) {
        try {
            Intent intent = installIntent(context, uriFile);
            context.startActivity(intent);
            android.os.Process.killProcess(android.os.Process.myPid());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Intent installIntent(Context context, File uriFile) {
        final String type = "application/vnd.android.package-archive";
        Intent intent = new Intent(Intent.ACTION_VIEW);
        //setFlag会清除之前的flag，addFlag则不会
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        Uri data = Uri.fromFile(uriFile);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            //防止App挂掉，权限被回收
            intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
            data = FileProvider.getUriForFile(context, getProviderPath(context), uriFile);
        }
        intent.setDataAndType(data, type);
        return intent;
    }

    /**
     * 卸载app
     *
     * @param packageName 要卸载程序的包名
     */
    public static void uninstall(Activity context, String packageName) {
        try {
            Uri packageURI = Uri.parse("package:" + packageName);
            Intent intent = new Intent(Intent.ACTION_DELETE, packageURI);
            context.startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据包名判断程序是否安装
     * 注意Android版本，11及之后可能有问题
     */
    public static boolean isAvailable(Context context, String packageName) {
        try {// 获取packageManager
            final PackageManager packageManager = context.getPackageManager();
            // 获取所有已安装程序的包信息
            List<PackageInfo> packageInfos = packageManager.getInstalledPackages(0);
            // 用于存储所有已安装程序的包名
            List<String> packageNames = new ArrayList<>();
            // 从pinfo中将包名字逐一取出，压入pName list中
            for (int i = 0; i < packageInfos.size(); i++) {
                String packName = packageInfos.get(i).packageName;
                packageNames.add(packName);
            }
            // 判断packageNames中是否有目标程序的包名，有TRUE，没有FALSE
            return packageNames.contains(packageName);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据文件判断是否安装了指定的软件
     */
    public static boolean isAvailable(Context context, File file) {
        try {
            boolean isEmpty = TextUtils.isEmpty(getPackageName(context, file.getAbsolutePath()));
            boolean isAvailable = isAvailable(context, getPackageName(context, file.getAbsolutePath()));
            return !isEmpty && isAvailable;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 根据文件路径获取包名
     *
     * @param filePath 文件路径
     */
    public static String getPackageName(Context context, String filePath) {
        try {
            PackageManager packageManager = context.getPackageManager();
            PackageInfo info = packageManager.getPackageArchiveInfo(filePath, PackageManager.GET_ACTIVITIES);
            if (info != null) {
                ApplicationInfo appInfo = info.applicationInfo;
                return appInfo.packageName;  //得到安装包名称
            }
            return "";
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    public static String getProviderPath(Context context) {
        return context.getPackageName() + ".provider";
    }

    /**
     * apk当前版本号
     */
    public static String apkVersion(Context context) {
        try {
            PackageManager pm = context.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
            // getPackageName()是你当前类的包名,0代表是获取版本信息
            return pi.versionName;
        } catch (Exception e) {
            e.printStackTrace();
            return "unknown";
        }
    }

    /**
     * 获取设备的序列号
     * Android-Q(10.0)及以上将获取不到,请自行实现获取设备信息
     * 其他版本需要以下权限
     * &lt;uses-permission android:name="android.permission.READ_PHONE_STATE"/&gt;
     */
    @SuppressLint("MissingPermission")
    public static String serial() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            return "unknown";
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            return Build.getSerial();
        } else {
            return Build.SERIAL;
        }
    }

    public static String getDataSize(long var0) {
        DecimalFormat var2 = new DecimalFormat("###.00");
        return var0 < 1024L ? var0 + "bytes" :
                var0 < 1048576L ? var2.format((float) var0 / 1024.0F) + "KB" :
                        var0 < 1073741824L ? var2.format((float) var0 / 1024.0F / 1024.0F) + "MB" :
                                "error";
    }

    public static String getSize(Context context, long size) {
        return Formatter.formatFileSize(context, size);
    }

    /**
     * 获取设备分辨率(获取带虚拟按键手机的屏幕分辨率)
     **/
    public static String getDisplay(Context context) {
        return getDisplayWidth(context) + "*" + getDisplayHeight(context);
    }

    public static int getDisplayWidth(Context context) {
        DisplayMetrics metrics = new DisplayMetrics();
        WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        if (null == manager)
            return -1;
        Display display = manager.getDefaultDisplay();
        display.getMetrics(metrics);
        DisplayMetrics dm = new DisplayMetrics();
        try {
            Class<?> c = Class.forName("android.view.Display");
            Method method = c.getMethod("getRealMetrics", DisplayMetrics.class);
            method.invoke(display, dm);
            return dm.widthPixels;
        } catch (Exception e) {
            return metrics.widthPixels;
        }
    }

    public static int getDisplayHeight(Context context) {
        DisplayMetrics metrics = new DisplayMetrics();
        WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        if (null == manager)
            return -1;
        Display display = manager.getDefaultDisplay();
        display.getMetrics(metrics);
        DisplayMetrics dm = new DisplayMetrics();
        try {
            Class<?> c = Class.forName("android.view.Display");
            Method method = c.getMethod("getRealMetrics", DisplayMetrics.class);
            method.invoke(display, dm);
            return dm.heightPixels;
        } catch (Exception e) {
            return metrics.heightPixels;
        }
    }

    /**
     * 获取屏幕尺寸最小
     */
    public static int getDisplayMinSize(Context context) {
        DisplayMetrics metrics = new DisplayMetrics();
        WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        if (null == manager)
            return -1;
        Display display = manager.getDefaultDisplay();
        display.getMetrics(metrics);
        DisplayMetrics dm = new DisplayMetrics();
        try {
            Class<?> c = Class.forName("android.view.Display");
            Method method = c.getMethod("getRealMetrics", DisplayMetrics.class);
            method.invoke(display, dm);
            return Math.min(dm.heightPixels, dm.widthPixels);
        } catch (Exception e) {
            return Math.min(metrics.heightPixels, metrics.widthPixels);
        }
    }

    /**
     * 兼容Android Q
     * &lt;uses-permission android:name="android.permission.INTERNET"/&gt;
     */
    public static String ipv4() {
        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
                NetworkInterface inter = en.nextElement();
                for (Enumeration<InetAddress> addresses = inter
                        .getInetAddresses(); addresses.hasMoreElements(); ) {
                    InetAddress inetAddress = addresses.nextElement();
                    //IPV4地址判断
                    boolean ipv4 = inetAddress instanceof Inet4Address;
                    //此行条件可不用加以判断
                    boolean linkLocal = inetAddress.isLinkLocalAddress();
                    if (!inetAddress.isLoopbackAddress() /*&& !linkLocal*/ && ipv4) {
                        return inetAddress.getHostAddress();
                    }
                }
            }
            return "";
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 获取设备本地IP
     */
    public static InetAddress inetAddress() {
        InetAddress ip = null;
        try {
            //列举
            Enumeration<NetworkInterface> en_netInterface = NetworkInterface.getNetworkInterfaces();
            while (en_netInterface.hasMoreElements()) {//是否还有元素
                NetworkInterface ni = en_netInterface.nextElement();//得到下一个元素
                Enumeration<InetAddress> en_ip = ni.getInetAddresses();//得到一个ip地址的列举
                while (en_ip.hasMoreElements()) {
                    ip = en_ip.nextElement();
                    if (!ip.isLoopbackAddress())
                        break;
                    else
                        ip = null;
                }
                if (ip != null) {
                    break;
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return ip;
    }

    /**
     * {@link #ipv4()}
     */
    public static String ipv6() {
        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
                NetworkInterface inter = en.nextElement();
                for (Enumeration<InetAddress> addresses = inter
                        .getInetAddresses(); addresses.hasMoreElements(); ) {
                    InetAddress inetAddress = addresses.nextElement();
                    //IPV6地址判断
                    boolean ipv6 = inetAddress instanceof Inet6Address;
                    //此行条件可不用加以判断
                    boolean linkLocal = inetAddress.isLinkLocalAddress();
                    if (!inetAddress.isLoopbackAddress() /*&& !linkLocal*/ && ipv6) {
                        return inetAddress.getHostAddress();
                    }
                }
            }
            return "";
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 兼容Android Q
     * &lt;uses-permission android:name="android.permission.INTERNET"/&gt;
     */
    public static String macAddress() {
        String wifiMac;
        String wiredMac = getWiredMac();
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M)
            wifiMac = getWifiMacM().toUpperCase();
        else wifiMac = getWifiMacN().toUpperCase();
        return TextUtils.isEmpty(wifiMac) ? wiredMac : wifiMac;
    }

    /**
     * 6.0及以下设备获取mac地址
     */
    private static String getWifiMacM() {
        try {
            List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
            for (NetworkInterface nif : all) {
                if (!nif.getName().equalsIgnoreCase("wlan0")) continue;
                byte[] macBytes = nif.getHardwareAddress();
                if (macBytes == null)
                    return "";
                StringBuilder res1 = new StringBuilder();
                for (byte b : macBytes) {
                    res1.append(String.format("%02X:", b));
                }
                if (res1.length() > 0) {
                    res1.deleteCharAt(res1.length() - 1);
                }
                return res1.toString().toUpperCase();
            }
        } catch (Exception ex) {
            return "";
        }
        return "";
    }

    /**
     * 7.0及以上设备获取mac地址
     * 9.0可正常使用
     * 10的设备未测试
     */
    private static String getWifiMacN() {
        String macSerial = "";
        try {
            String str = "";
            Process pp = Runtime.getRuntime().exec("cat /sys/class/net/wlan0/address ");
            InputStreamReader ir = new InputStreamReader(pp.getInputStream());
            LineNumberReader input = new LineNumberReader(ir);
            while (null != str) {
                str = input.readLine();
                if (str != null) {
                    macSerial = str.trim();// 去空格
                    break;
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            macSerial = "";
        }
        if (TextUtils.isEmpty(macSerial)) {
            try {
                return loadFileAsString().toUpperCase().substring(0, 17);
            } catch (Exception e) {
                e.printStackTrace();
                return "";
            }
        }
        return macSerial;
    }

    private static String loadFileAsString() {
        try (FileReader reader = new FileReader("/sys/class/net/eth0/address")) {
            StringBuilder builder = new StringBuilder();
            char[] buffer = new char[4096];
            int readLength = reader.read(buffer);
            while (readLength >= 0) {
                builder.append(buffer, 0, readLength);
                readLength = reader.read(buffer);
            }
            String text = builder.toString();
            reader.close();
            return text;
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 获取网线-有线的MAC地址
     * 无线和有线都可用
     */
    public static String getWiredMac() {
        String macAddress = "";
        try {
            InetAddress ip = inetAddress();
            byte[] b = NetworkInterface.getByInetAddress(ip)
                    .getHardwareAddress();
            StringBuilder buffer = new StringBuilder();
            for (int i = 0; i < b.length; i++) {
                if (i != 0) {
                    buffer.append(':');
                }
                String str = Integer.toHexString(b[i] & 0xFF);
                buffer.append(str.length() == 1 ? 0 + str : str);
            }
            macAddress = buffer.toString().toUpperCase();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return macAddress;
    }

    /**
     * android10之后get设备的信息
     */
    @SuppressLint("HardwareIds")
    public static String androidId(Application application) {
        return Settings.Secure.getString(application.getContentResolver(), Settings.Secure.ANDROID_ID);
    }
}
